package com.hopu.haogoumall.vxapi.controller;


import com.hopu.haogoumall.core.utils.ExceptionCode;
import com.hopu.haogoumall.core.utils.ResponseUtils;
import com.hopu.haogoumall.db.module.HaogoumallUser;
import com.hopu.haogoumall.db.service.VxLoginService;
import net.sf.jsqlparser.schema.MultiPartName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * @Package: com.hopu.haogoumall.hgmall.controller
 * @ClassName: LoginController
 * @Author: xiaoBao
 * @CreateTime: 2020-11-19 8:52
 * @Description: 【登录验证功能表现层】：验证用户名是否存在、验证账号密码是否正确
 */

/**@RestController注解：定义表现层，并且在每个使用@RequestMapping注解的方法上自动添加@ResponseBody注解*/
@RestController
/**@RequestMapping注解：在类名上定义的@RequestMapping注解用于窄化（简化）请求路径；*/
@RequestMapping("/wx/")
public class VxLoginController {
    /**通过工厂获取Logger日志对象用于输出日志信息*/
    Logger logger = LoggerFactory.getLogger(getClass());
    /**引入Service业务层*/
    @Resource
    private VxLoginService vxLoginService;


    /**
     * 【getLogin】 登录验证功能：验证账号密码是否正确（在验证账号密码是否正确前验证账号是否存在）
     * @param user 用户名和密码；
     * @return 将操作结果的响应数据返回给前端。
     */
    @RequestMapping("auth/login")
    public Object getLogin(HaogoumallUser user, HttpServletRequest request){
        //在验证账号密码是否正确前判断账号是否存在（调用业务层逻辑）
        HaogoumallUser userName = vxLoginService.checkUserByUserName(user);
        if(userName == null){
            //为空则表示用户名不存在
            return ResponseUtils.fail(ExceptionCode.AUTH_INVALID_ACCOUNT,"用户名不存在");
        }
        else //如果用户名存在则判断账号密码是否正确
            {
                //调用业务层逻辑：验证用户名和密码是否正确，返回一个User对象；
                HaogoumallUser mallUser = vxLoginService.checkUserByUserNameAndPassword(user);

                //判断业务层执行持久层操作返回的User对象是不为空，如果不为空则表示用户名和密码正确；
                if(mallUser != null){
                    //在响应登录成功信息给前端前，更新用户的最后一次登录时间和IP地址；
                    //获取当前系统时间和IP，设置实体类的属性；
                    user.setUserLastLoginTime(LocalDateTime.now());
                    user.setUserLastLoginIp(request.getRemoteAddr());
                    //调用业务层逻辑
                    int resultOne = vxLoginService.updateUserLastLoginTimeAndUserLastLoginIp(user);
                    if(resultOne > 0){
                        logger.info("最后一次登录时间和IP地址更新成功");
                    }

                    //保存当前用户登录的会话Session（此方法会将当前客户端的SessionID传入响应头的Cookie中）
                    request.getSession().setAttribute("accountInfo",user);
                    //调用操作成功响应方法，并返回对象给前端
                    return ResponseUtils.ok(mallUser);
                }else {
                    //如果为空则表示用户名或密码错误,返回错误码和错误信息；
                    return ResponseUtils.fail(ExceptionCode.AUTH_INVALID_ACCOUNT,"用户名或密码错误");
                }
            }
    }


    /**
     * 【reigsterUser】 注册账号
     * @param user 用户名、密码、昵称、电话号码、性别；
     * @return 将响应数据返回给前端。
     */
    @RequestMapping("auth/register")
    public Object reigsterUser(HaogoumallUser user,HttpServletRequest request) throws IOException {
        //在注册账号前判断用户名是否存在（调用业务层逻辑）
        HaogoumallUser userName = vxLoginService.checkUserByUserName(user);
        //验证手机号码是否已注册（调用业务层逻辑）
        HaogoumallUser userMobile = vxLoginService.checkMobile(user);
        if(userName != null){
            return ResponseUtils.fail(ExceptionCode.AUTH_NAME_REGISTERED,"用户名已注册");
        }else if(userMobile != null){
            return ResponseUtils.fail(ExceptionCode.AUTH_MOBILE_UNREGISTERED,"手机号已注册");
        }else {
            /**
             * 获取前端传输的文件（图片、文件等等），并上传到阿里云空间（对象存储OSS）中的Bucket进行管理
             *  具体步骤：
             *      1、获取微信小程序前端发送请求wx.uploadFile方法传输的文件；
             *      2、将HttpServlet的request强转成SpringMVC文件解析器的request（用于获取请求中的文件）；
             *      3、通过MultipartFile的getFile(fileName)方法获取到文件；
             *      4、将文件转成流（上传文件到OSS对象存储需要一个文件流的参数，所以这里需要将文件转成流传递给上传文件的方法）；
             *      5、通过MultipartFile的getOriginalFilename()方法获取文件的全名称，并通过String的split方法分割字符串（获取文件的后缀名）；
             *      6、获取使用String的split方法返回的数组的最后一个索引（文件后缀名）
             *      7、声明Bucket中文件的具体路径（需要上传的文件夹）
             *      8、定义一个新的文件名（Bucket文件路径+用户名+文件后缀）
             *      9、调用业务层逻辑（传递OSS需要的文件路径 和 文件流参数），在执行某个功能将路径插入数据库前，把文件上传到OSS对象存储Bucket中。
             */
            // 将HttpServlet的request强转成SpringMVC文件解析器的request
            MultipartHttpServletRequest ms =(MultipartHttpServletRequest) request;
            //获取请求中传输的文件
            MultipartFile file = ms.getFile("avatar");
            //将文件转成IO流（抛出异常）
            InputStream inputStream = file.getInputStream();
            //获取文件的类型(通过split方法截取后缀名) 返回一个数组类型的String
            String[] fileName = file.getOriginalFilename().split("\\.");
            //获取最后一个索引的字符（文件后缀名）
            String suffix = fileName[fileName.length-1];
            //Bucket 上传文件的路径
            String filePath = "images/userAvatar/";
            //定义一个新的上传文件名           images/userAvatar/username.后缀
            String objectName = filePath + user.getUserUsername() + "." + suffix;


            //设置当前账号的添加时间
            user.setUserAddTime(LocalDateTime.now());
            user.setUserUpdateTime(LocalDateTime.now());
            //调用业务层逻辑：注册账号
            int successResult = vxLoginService.addUser(user,objectName,inputStream);
            if (successResult > 0){
                logger.info("账号注册成功");
            }
            return ResponseUtils.ok(successResult);
        }
    }


    /**
     * 【checkLogin】验证账号是否登录 测试
     * @param request 获取请求头信息；
     * @return 返回当前判断结果。
     */
    @RequestMapping("checkLogin")
    public boolean checkLogin(HttpServletRequest request){
        //通过Session的getAttribute()方法的name获取Session会话的属性值
        Object accountInfo = request.getSession().getAttribute("accountInfo");

        //判断当前会话是否为空，如果不为空表示账号已登录；
        if(accountInfo != null){
            return true;
        }else{
            return false;
        }
    }
}
